package com.cleaningcloud.erp.service.impl;

import com.cleaningcloud.common.core.exception.ServiceException;
import com.cleaningcloud.common.core.utils.DateUtils;
import com.cleaningcloud.common.core.utils.StringUtils;
import com.cleaningcloud.common.core.utils.UniqueIdUtils;
import com.cleaningcloud.common.security.utils.CommunityTypeConversionUtils;
import com.cleaningcloud.common.security.utils.SecurityUtils;
import com.cleaningcloud.erp.domain.*;
import com.cleaningcloud.erp.domain.dto.ErpProcureDetailsDto;
import com.cleaningcloud.erp.domain.dto.ErpProcureDto;
import com.cleaningcloud.erp.domain.excelImport.ProcureExcelImport;
import com.cleaningcloud.erp.domain.vo.ErpProcureDetailsVo;
import com.cleaningcloud.erp.domain.vo.ErpProcureVo;
import com.cleaningcloud.erp.mapper.*;
import com.cleaningcloud.erp.service.IErpProcureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 采购单Service业务层处理
 *
 * @author cleaningcloud
 * @date 2024-09-26
 */
@Service
public class ErpProcureServiceImpl implements IErpProcureService {
    @Autowired
    private ErpProcureMapper erpProcureMapper;

    @Autowired
    private ErpSupplierMapper erpSupplierMapper;

    @Autowired
    private ErpCommodityMapper erpCommodityMapper;

    @Autowired
    private ErpCommodityUnitMapper erpCommodityUnitMapper;

    @Autowired
    private ErpSupplierCommodityMapper erpSupplierCommodityMapper;

    @Autowired
    private ErpProcureDetailsMapper procureDetailsMapper;

    @Autowired
    private ErpAccountsPayableMapper erpAccountsPayableMapper;

    @Autowired
    private ErpWarehousingMapper erpWarehousingMapper;

    /**
     * 查询采购单
     *
     * @param procureId 采购单主键
     * @return 采购单
     */
    @Override
    public ErpProcureVo selectErpProcureByProcureId(Long procureId) {
        ErpProcureVo erpProcureVo = erpProcureMapper.selectErpProcureByProcureId(procureId);
        for (ErpProcureDetailsVo erpProcureDetailsVo : erpProcureVo.getDetailsList()) {
            erpProcureDetailsVo.setSupplierCommodityType(CommunityTypeConversionUtils.conversion(erpProcureDetailsVo.getSupplierCommodityType()));
        }
        return erpProcureVo;
    }

    /**
     * 查询采购单列表
     *
     * @param erpProcure 采购单
     * @return 采购单
     */
    @Override
    public List<ErpProcureVo> selectErpProcureList(ErpProcureDto erpProcure) {
        return erpProcureMapper.selectErpProcureList(erpProcure);
    }

    /**
     * 新增采购单
     *
     * @param erpProcure 采购单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertErpProcure(ErpProcureDto erpProcure) {
        erpProcure.setCreateTime(DateUtils.getNowDate());
        erpProcure.setFlag("Y");
        erpProcure.setLogisticsStauts("0");
        erpProcure.setCreateId(SecurityUtils.getUserId());
        erpProcure.setCreateName(SecurityUtils.getUsername());
        erpProcure.setProcureNo("CG" + UniqueIdUtils.generateUniqueId());
        erpProcureMapper.insertErpProcure(erpProcure);
        // 新增采购明细
        if (erpProcure.getDetailsList() != null && !erpProcure.getDetailsList().isEmpty()) {
            erpProcure.getDetailsList().forEach(item -> {
                item.setProcureId(erpProcure.getProcureId());
                item.setProcureOdd(erpProcure.getProcureNo());
            });
            procureDetailsMapper.batchInsert(erpProcure.getDetailsList());
        }

        return 1;
    }

    /**
     * 修改采购单
     *
     * @param erpProcure 采购单
     * @return 结果
     */
    @Override
    @Transactional
    public int updateErpProcure(ErpProcureDto erpProcure) {
        // 删除之前绑定的采购明细数据
        procureDetailsMapper.deleteByProcureId(erpProcure.getProcureId());
        // 新增采购明细
        if (erpProcure.getDetailsList() != null && !erpProcure.getDetailsList().isEmpty()) {
            erpProcure.getDetailsList().forEach(item -> {
                item.setProcureId(erpProcure.getProcureId());
                item.setProcureOdd(erpProcure.getProcureNo());
            });
            procureDetailsMapper.batchInsert(erpProcure.getDetailsList());
        }
        return erpProcureMapper.updateErpProcure(erpProcure);
    }

    /**
     * 批量删除采购单
     *
     * @param procureIds 需要删除的采购单主键
     * @return 结果
     */
    @Override
    public int deleteErpProcureByProcureIds(Long[] procureIds) {
        return erpProcureMapper.deleteErpProcureByProcureIds(procureIds);
    }

    /**
     * 删除采购单信息
     *
     * @param procureId 采购单主键
     * @return 结果
     */
    @Override
    public int deleteErpProcureByProcureId(Long procureId) {
        return erpProcureMapper.deleteErpProcureByProcureId(procureId);
    }

    @Override
    @Transactional
    public int audit(ErpProcure erpProcure) {
        ErpProcureVo procure = erpProcureMapper.selectErpProcureByProcureId(erpProcure.getProcureId());
        if (procure != null) {
            procure.setApproveId(SecurityUtils.getUserId());
            procure.setApproveName(SecurityUtils.getUsername());
            procure.setApproveTime(DateUtils.getNowDate());
            procure.setProcureStatus(erpProcure.getProcureStatus());
            // 审核通过时 修改采购批次数量 + 1
            if (procure.getProcureStatus() == 2) {
                for (ErpProcureDetailsVo erpProcureDetailsVo : procure.getDetailsList()) {
                    //修改采购单明细最大采购批次
                    ErpProcureDetails epd = new ErpProcureDetails();
                    epd.setSupplierId(erpProcure.getSupplierId());
                    epd.setCommodityId(erpProcureDetailsVo.getCommodityId());
                    ErpProcureDetails details = procureDetailsMapper.getMaxProcureBatch(epd);
                    if(null != details) {
                        erpProcureDetailsVo.setProcureBatch(details.getProcureBatch() + 1);
                    }else{
                        erpProcureDetailsVo.setProcureBatch(1);
                    }
                    procureDetailsMapper.updateErpProcureDetails(erpProcureDetailsVo);

                    // 计算商品成本价 加权平均
                    if(erpProcureDetailsVo.getProcureBatch() > 1){
                        ErpProcureDetailsDto query = new ErpProcureDetailsDto();
                        query.setSupplierId(procure.getSupplierId());
                        query.setProcureStatus(2);
                        query.setCommodityId(erpProcureDetailsVo.getCommodityId());
                        query.setProcureBatch(1);//过滤为NULL值
                        List<ErpProcureDetails> detailsList = procureDetailsMapper.selectErpProcureDetailsList(query);
                        // 采购价累计
                        BigDecimal sumProcurePrice = new BigDecimal("0.0");
                        if (!detailsList.isEmpty()) {
                            sumProcurePrice = detailsList.stream().map(ErpProcureDetails::getProcurePrice).reduce(BigDecimal::add).get();
                        }
                        // 累计本次价格
                        sumProcurePrice = sumProcurePrice.add(erpProcureDetailsVo.getProcurePrice());
                        // 成本价
                        BigDecimal costPrice = sumProcurePrice.divide(BigDecimal.valueOf(erpProcureDetailsVo.getProcureBatch()), 2, RoundingMode.HALF_UP);
                        erpCommodityUnitMapper.updateCostPriceByCommodityId(costPrice, erpProcureDetailsVo.getCommodityKey());
                    }
                }
                // 生成应付款单数据
                ErpAccountsPayable erpAccountsPayable = insertAccountsPayable(procure, 0);
                // 生成采购入库数据
                ErpWarehousing erpWarehousing = new ErpWarehousing();
                // 采购入库明细
                List<ErpWarehousingDetails> erpWarehousingDetailsList = new ArrayList<>();
                // 预计入库量  统计采购明细采购数量
                int answerScheduledReceipt = (int) procure.getDetailsList()
                        .stream()
                        .mapToDouble(ErpProcureDetails::getProcureNumber)
                        .sum();
                // 采购入库单字段赋值
                erpWarehousing.setAnswerScheduledReceipt(answerScheduledReceipt);
                erpWarehousing.setPayableId(erpAccountsPayable.getPayableId());
                erpWarehousing.setWarehousingType(erpAccountsPayable.getOddType());
                erpWarehousing.setProcureOdd(erpProcure.getProcureNo());
                erpWarehousing.setCreateId(SecurityUtils.getUserId());
                erpWarehousing.setCreateName(SecurityUtils.getUsername());
                erpWarehousing.setCreateTime(new Date());
                erpWarehousing.setWarehousingNo("GY" + UniqueIdUtils.generateUniqueId());
                erpWarehousing.setWarehousingStatus(1);
                erpWarehousing.setFlag("Y");
                erpWarehousingMapper.insertErpWarehousing(erpWarehousing);
                // 采购单明细复制到采购入库明细
                erpWarehousingDetailsList = getErpWarehousingDetails(procure.getDetailsList(), erpWarehousing);
                if (!erpWarehousingDetailsList.isEmpty()) {
                    erpWarehousingMapper.batchWarehousingDetailsInsert(erpWarehousingDetailsList);
                }
            } else {
                procure.setRejectTime(DateUtils.getNowDate());
                procure.setRejectReason(erpProcure.getRejectReason());
            }
        }
        return erpProcureMapper.updateErpProcure(procure);
    }

    @Override
    public int logistics(ErpProcure erpProcure) {
        return erpProcureMapper.updateErpProcure(erpProcure);
    }

    @Override
    @Transactional
    public String importErpProcure(List<ProcureExcelImport> procureExcelImportList, Boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(procureExcelImportList) || procureExcelImportList.isEmpty()) {
            throw new ServiceException("导入采购单不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 采购单数据
        ErpProcureDto erpProcure = new ErpProcureDto();
        // 采购明细
        List<ErpProcureDetails> detailsList = new ArrayList<>();
        Long supplierId = null;
        for (ProcureExcelImport procureExcelImport : procureExcelImportList) {
            try {
                // 取出第一条为采购单数据
                if (StringUtils.isNull(erpProcure.getProcureNo())) {
                    erpProcure.setProcureNo("CG" + UniqueIdUtils.generateUniqueId());
                    erpProcure.setProcureTime(procureExcelImport.getProcureTime());
                    erpProcure.setLogisticsCost(procureExcelImport.getLogisticsCost());
                    erpProcure.setLogisticsMethod(procureExcelImport.getLogisticsMethod());
                    erpProcure.setOtherCost(procureExcelImport.getOtherCost());
                    erpProcure.setOtherMethod(procureExcelImport.getOtherMethod());
                    // 根据供应商编号查询供应商数据
                    supplierId = erpSupplierMapper.selectSupplierByNo(procureExcelImport.getSupplierNo());
                    if (supplierId == null) {
                        throw new RuntimeException("供应商查询失败,请检查供应商编码是否正确！");
                    }
                    erpProcure.setSupplierId(supplierId);
                    erpProcure.setFlag("Y");
                    erpProcure.setApproveId(SecurityUtils.getUserId());
                    erpProcure.setApproveName(SecurityUtils.getUsername());
                    erpProcure.setApproveTime(DateUtils.getNowDate());
                    erpProcure.setProcureTime(DateUtils.getNowDate());
                    erpProcure.setCreateId(SecurityUtils.getUserId());
                    erpProcure.setCreateName(SecurityUtils.getUsername());
                    erpProcure.setCreateTime(DateUtils.getNowDate());
                    erpProcure.setLogisticsStauts("0");
                    erpProcure.setProcurePersonId(SecurityUtils.getUserId());
                    erpProcure.setProcureStatus(1);
                    erpProcure.setPayAmount(new BigDecimal("0.0"));
                    if (erpProcure.getLogisticsCost() != null) {
                        erpProcure.setPayAmount(erpProcure.getPayAmount().add(erpProcure.getLogisticsCost()));
                    }
                    if (erpProcure.getOtherCost() != null) {
                        erpProcure.setPayAmount(erpProcure.getPayAmount().add(erpProcure.getOtherCost()));
                    }
                }
                // 组装采购商品数据
                ErpProcureDetails procureDetails = new ErpProcureDetails();
                procureDetails.setProcureId(erpProcure.getProcureId());
                procureDetails.setProcureNumber(procureExcelImport.getProcureNumber());
                // 根据商品编号查询商品
                ErpSupplierCommodity erpSupplierCommodity = erpSupplierCommodityMapper.selectErpSupplierCommodityBySupplierCommodityNo(procureExcelImport.getCommodityNo(),supplierId);
                if (erpSupplierCommodity == null) {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、商品编号[" + procureExcelImport.getCommodityNo() + "]查询失败,请检查是否正确");
                } else {
                    if (!Objects.equals(erpSupplierCommodity.getSupplierId(), erpProcure.getSupplierId())) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、商品编号[" + procureExcelImport.getCommodityNo() + "]不属于供应商[" + procureExcelImport.getSupplierNo() + "],请检查是否正确");
                    } else {
                        // 查询商品明细
                        procureDetails.setProcureOdd(erpProcure.getProcureNo());
                        procureDetails.setCommodityId(erpSupplierCommodity.getSupplierCommodityId());
                        procureDetails.setProcurePrice(erpSupplierCommodity.getSupplierCommodityQuotation());
                        procureDetails.setProcureNumber(procureExcelImport.getProcureNumber());
                        procureDetails.setSubtotal(erpSupplierCommodity.getSupplierCommodityQuotation().multiply(BigDecimal.valueOf(procureDetails.getProcureNumber())));
                        // 累计总金额
                        erpProcure.setPayAmount(erpProcure.getPayAmount().add(procureDetails.getSubtotal()));
                        detailsList.add(procureDetails);
                        successNum++;
                        successMsg.append("<br/>" + successNum + "、商品编号 " + procureExcelImport.getCommodityNo() + " 导入成功");
                    }
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、商品编号 " + procureExcelImport.getCommodityNo() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            if (detailsList.size() > 0) {
                erpProcure.setDetailsList(detailsList);
                // 插入采购单
                erpProcureMapper.insertErpProcure(erpProcure);
                erpProcure.getDetailsList().forEach(item -> {
                    item.setProcureId(erpProcure.getProcureId());
                    item.setProcureOdd(erpProcure.getProcureNo());
                });
                // 批量新增采购明细
                procureDetailsMapper.batchInsert(erpProcure.getDetailsList());
                // 生成应付款单数据
//                ErpAccountsPayable erpAccountsPayable = insertAccountsPayable(erpProcure, 1);
//                // 生成采购入库数据
//                ErpProcureVo procure = erpProcureMapper.selectErpProcureByProcureId(erpProcure.getProcureId());
//                ErpWarehousing erpWarehousing = new ErpWarehousing();
//                // 采购入库明细
//                List<ErpWarehousingDetails> erpWarehousingDetailsList = new ArrayList<>();
//                // 预计入库量  统计采购明细采购数量
//                int answerScheduledReceipt = (int) procure.getDetailsList()
//                        .stream()
//                        .mapToDouble(ErpProcureDetails::getProcureNumber)
//                        .sum();
//                // 采购入库单字段赋值
//                erpWarehousing.setAnswerScheduledReceipt(answerScheduledReceipt);
//                erpWarehousing.setPayableId(erpAccountsPayable.getPayableId());
//                erpWarehousing.setWarehousingType(erpAccountsPayable.getOddType());
//                erpWarehousing.setProcureOdd(erpProcure.getProcureNo());
//                erpWarehousing.setCreateId(SecurityUtils.getUserId());
//                erpWarehousing.setCreateName(SecurityUtils.getUsername());
//                erpWarehousing.setCreateTime(new Date());
//                erpWarehousing.setWarehousingNo("GY" + UniqueIdUtils.generateUniqueId());
//                erpWarehousing.setWarehousingStatus(1);
//                erpWarehousing.setFlag("Y");
//                erpWarehousingMapper.insertErpWarehousing(erpWarehousing);
//                // 采购单明细复制到采购入库明细
//                erpWarehousingDetailsList = getErpWarehousingDetails(procure.getDetailsList(), erpWarehousing);
//                if (erpWarehousingDetailsList.size() > 0) {
//                    erpWarehousingMapper.batchWarehousingDetailsInsert(erpWarehousingDetailsList);
//                }
            }
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共采购商品 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    private ErpAccountsPayable insertAccountsPayable(ErpProcure erpProcure, Integer oddStatus) {
        ErpAccountsPayable erpAccountsPayable = new ErpAccountsPayable();
        erpAccountsPayable.setOddNo(erpProcure.getProcureNo());
        erpAccountsPayable.setOddType(1);
        erpAccountsPayable.setBusinessId(erpProcure.getSupplierId());
        erpAccountsPayable.setOddDate(new Date());
        erpAccountsPayable.setOddStatus(oddStatus);
        erpAccountsPayable.setOddSumMoney(erpProcure.getPayAmount());
        erpAccountsPayable.setFlag("Y");
        erpAccountsPayable.setOddMoney(erpProcure.getPayAmount());
        erpAccountsPayable.setUserId(SecurityUtils.getUserId());
        erpAccountsPayable.setUserName(SecurityUtils.getUsername());
        erpAccountsPayableMapper.insertErpAccountsPayable(erpAccountsPayable);
        return erpAccountsPayable;
    }

    /**
     * 根据采购单生成采购入库明细
     *
     * @param list
     * @param erpOutbound
     * @return
     */
    public List<ErpWarehousingDetails> getErpWarehousingDetails(List<ErpProcureDetailsVo> list, ErpWarehousing erpWarehousing) {
        return list
                .stream()
                .map(
                        obj -> {
                            ErpWarehousingDetails warehousingDetails = new ErpWarehousingDetails();
                            warehousingDetails.setWarehousingId(erpWarehousing.getWarehousingId());
                            warehousingDetails.setWarehousingOdd(erpWarehousing.getWarehousingNo());
                            warehousingDetails.setCommodityId(obj.getCommodityKey());
                            warehousingDetails.setPendingNumber(obj.getProcureNumber());
                            warehousingDetails.setProcureNumber(obj.getProcureNumber());
                            return warehousingDetails;
                        }
                ).collect(Collectors.toList());
    }


}
